use std::cmp::min;
use std::io::{self, BufRead};

fn main() {
    // 使用 `BufReader` 来高效读取输入
    let mut lines = io::stdin().lock().lines();

    // 读取第一行，获取节点数 `n`
    let n = lines.next().unwrap().unwrap().trim().parse().unwrap();

    // 初始化成本矩阵 `cost`
    let mut cost = vec![vec![0; n]; n];
    for i in 0..n {
        cost[i] = lines
            .next()
            .unwrap()
            .unwrap()
            .split_whitespace()
            .map(|s| s.parse().unwrap())
            .collect();
    }

    // 初始化动态规划表 `dp`
    let mut dp = vec![vec![i32::MAX; n]; 1 << n];
    dp[1][0] = 0;

    // 动态规划逻辑
    for mask in 1..(1 << n) {
        for u in 0..n {
            if dp[mask][u] == i32::MAX {
                continue;
            }
            for v in 1..n {
                if v == u || (mask & (1 << v)) != 0 {
                    continue; // 跳过自身或已访问的节点
                }
                let new_mask = mask | (1 << v);
                dp[new_mask][v] = min(dp[new_mask][v], dp[mask][u] + cost[u][v]);
            }
        }
    }

    // 计算结果
    let final_mask = (1 << n) - 1;
    let mut res = i32::MAX;
    for u in 1..n {
        if dp[final_mask][u] != i32::MAX {
            res = min(res, dp[final_mask][u] + cost[u][0]);
        }
    }

    // 输出结果
    if res == i32::MAX {
        println!("No valid path found");
    } else {
        println!("{}", res);
    }
}